A program in a computer system operates when a processor processes a routine that is written in machine language. One or more codes written in the machine language are herein referred to as “routines”.
Instructions included in the routine are processed by a processor in order one by one. However, a routine in most programs includes an instruction that changes one instruction to be processed next, to an instruction other than the one instruction, or to an instruction in another routine, depending on a condition. Such an instruction that changes an address of an instruction to be processed next is generally called a “branch instruction”.
FIG. 1 illustrates an example in which the order of processes is changed by a branch instruction. The name of a branch instruction and a code of an instruction vary depending on a processor. In an instruction set for a common processor, there are a jump instruction and a call and return instruction as the branch instruction. The call and return instruction may be divided into a call instruction and a return instruction. Hereinafter, the branch instruction is used as a term that collectively refers to the jump instruction, the call and return instructions, or the like.
As illustrated in FIG. 1, when an instruction A2 is a jump instruction, instead of an instruction A3 next to the instruction A2, an instruction A4 may be set as an instruction to be processed after the instruction A2. In addition, when the instruction A4 is a call instruction to call a routine B, the process proceeds to an instruction B1 in the routine B after execution of the instruction A4. After that, instructions B2 to B4 in the routine B are processed in order. In addition, when an instruction B5 is a return instruction, the process returns to an instruction A5 next to the instruction A4 in the routine A. The call instruction is used with the return instruction. When the return instruction is executed, a stack pointer is, for example, set up in order to hold a return address. Generally, the jump instruction is often used to branch in the same routine, and the call and return instructions are often used to branch to an instruction in another routine.
An individual instruction in a routine mainly includes an “operation code” that indicates the type of the instruction and an “operand” that indicates a value that is a calculation target of the instruction. Each operand of the jump instruction and the call instruction stores an address in which an instruction of the branch destination exists. In most cases, the address is represented by a relative address from the instruction of the branch source.
An address that is used in the embodiments may be a virtual address or may be a real address. In addition, in the embodiments, Java (registered trademark) may be used as an example, however, the embodiment is not limited to the use of Java.
A program that is written in Java is converted into byte code. The byte code is executed by a Java virtual machine (Java VM). Therefore, the program that is written in Java operates regardless of CPU as long as the computer supports the Java VM. Thus, Java has an advantage of operating in multiple platforms. A common Java VM sequentially converts “byte code” into machine language that is specific to a processor, and causes the processor to process the machine language. However, in the sequential conversion of the byte code, the processing costs often increase.
Therefore, there is a technology to convert byte code into a routine of the machine language, for each method, during program execution. Such technology is generally called “Just in time (JIT) compilation”.
FIG. 2 illustrates a process of a common JIT compiler. In Step 202, the JIT compiler converts a byte code of a method, which is a compilation target, into an intermediate code that is independent of a host machine. In Step 204, the JIT compiler converts the intermediate code into a machine language routine of the host machine. In Step 206, the machine language routine is written in a machine language routine area on a memory. As a result, all of the compiled methods are represented by the machine language routine that is specific to a processor, so that the processor may process the machine language routine directly. Hereinafter, a memory area to store a machine language routine that is generated by the JIT compiler is referred to as a “routine area”.
When the process of the program proceeds, a routine that is not used may occur, so that the routine area varies with time. That is, the number of routines and usage of the memory vary. The unused routine is open for another routine by executing garbage collection. However, there is a problem such as occurrence of fragments when the garbage collection is simply executed.
FIG. 3 illustrates the occurrence of fragments on the memory. A routine of methods includes a branch instruction in most cases. In a case in which an operand that indicates the branch destination is a relative address, when the routine that includes the branch instruction is simply moved, the branch instruction is issued to a wrong branch destination, undesirably. In addition, the above-described case is also applied to a case in which the branch destination is moved. Therefore, even when the unused routine increases and free spaces appear in the routine area, it is difficult to move the routine and collects the free memory areas. Therefore, the fragments remain.
Even when a virtual memory is used, the size of the routine area is limited. This is because the virtual memory area is not unlimited. Thus, the fragments may remain and weigh on the virtual memory resource even in the virtual memory space.
As a technology to defragment the memory area, there is compaction-type garbage collection to collect free memory areas. However, as described above, a routine that branches using a relative address is not allowed to be moved. Therefore, it is difficult to apply the compaction-type garbage collection for the routine area.
The minimum unit of the JIT compilation is a sub-routine that is called a method. When fragments occur, for example, a memory area that is used for a routine compiled by the JIT compiler might not be allocated because the size of the individual free memory areas is small even in a situation in which there is an enough room when all free memory areas are combined. When a memory is not allocated to a routine area, an application may terminate. In order to avoid such termination, the JIT compiler may stop compiling the method at the time. Alternatively, an optimization level of the JIT compiler may be reduced and the operation is switched to compilation that consumes a smaller memory area.
In the related art, a technology is discussed in which unauthorized memory access during memory compaction is avoided by starting garbage collection while blocking a user program by an I/O process or the like, and ending the I/O blocking before the garbage collection ends to restart the user program. Japanese Laid-open Patent Publication No. 2000-181723 is an example of the related art.
In addition, in the related art, a technology is discussed in which whether or not a method, on which the JIT compilation is performed, is allowed to be executed without generating a frame (area to store a local variable) is determined, a native code that is executed without generating a frame is generated for such a method, and a call of the method is streamlined. Japanese Laid-open Patent Publication No. 2005-284729 is an example of the related art.